package com.sci.util;

import com.sci.entity.User;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Component
public class JwtTokenUtil {

    // 配置注入
    @Value("${jwt.base-secret}")
    private String baseSecret;

    @Value("${jwt.base-issuer}")
    private String baseIssuer;

    @Value("${jwt.expiration.access}")
    private Long accessTokenExpiration; // 86400秒(24小时)

    private static final String TOKEN_TYPE_ACCESS = "access";

    /**
     * 生成访问令牌（24小时有效期）
     */
    public String generateAccessToken(User user) {
        Map<String, Object> claims = new HashMap<>();
        String userId = user.getWechatId();
        claims.put("userId", userId);
        claims.put("username", user.getUserName());
        claims.put("tokenType", TOKEN_TYPE_ACCESS);
        claims.put("sessionId", UUID.randomUUID().toString());

        return buildToken(claims, userId, baseIssuer, baseSecret, accessTokenExpiration);
    }

    /**
     * 构建JWT令牌
     */
    private String buildToken(Map<String, Object> claims, String subject,
                              String issuer, String secret, Long expiration) {
        SecretKey key = createHmacShaKey(secret);

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuer(issuer)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                .signWith(key, SignatureAlgorithm.HS256)
                .compact();
    }

    /**
     * 验证令牌
     */
    public boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            String tokenType = claims.get("tokenType", String.class);
            return !isTokenExpired(claims) && TOKEN_TYPE_ACCESS.equals(tokenType);
        } catch (ExpiredJwtException e) {
            throw new SecurityException("令牌已过期", e);
        } catch (UnsupportedJwtException | MalformedJwtException | SignatureException |
                 IllegalArgumentException e) {
            throw new SecurityException("无效的令牌", e);
        }
    }

    /**
     * 解析令牌
     */
    public Claims parseToken(String token) throws JwtException {
        try {
            return Jwts.parser()
                    .verifyWith(createHmacShaKey(baseSecret))
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (JwtException e) {
            throw new JwtException("令牌解析失败: " + e.getMessage(), e);
        }
    }

    /**
     * 检查令牌是否过期
     */
    public boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }

    /**
     * 创建HMAC-SHA密钥
     */
    private SecretKey createHmacShaKey(String secret) {
        byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 获取用户ID从令牌
     */
    public String getUserIdFromToken(String token) {
        return parseToken(token).getSubject();
    }
}